
#region Using Statements
using System;
using System.Collections.Generic;//using System.Xml.Serialization;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Graphics.PackedVector;
#endregion



namespace Pauliver
{
    #region PINPUT

    public enum PlayerIndex
    {
        One = 0,
        Two = 1,
        Three = 2,
        Four = 3
    };

    public class FakeGamePad :  GamePad
    {
        public FakeGamePad(PlayerIndex index)
            : base(index)
        {

        }
        
        public FakeGamePad(int index)
            : base(index)
        {

        }

        public void Read(PacketReader pr)
        {
            {
                byte mask = pr.ReadByte();
                if ((mask & 0x01) == 0x01){
                    ((FakeButtonWrapper)A).IsRegisterDown = true;
                }else{
                    ((FakeButtonWrapper)A).IsRegisterDown = false;
                }
                if ((mask & 0x02) == 0x02){
                    ((FakeButtonWrapper)B).IsRegisterDown = true;
                }else{
                    ((FakeButtonWrapper)B).IsRegisterDown = false;
                }
                if ((mask & 0x04) == 0x04){
                    ((FakeButtonWrapper)Back).IsRegisterDown = true;
                }else{
                    ((FakeButtonWrapper)Back).IsRegisterDown = false;
                }
                if ((mask & 0x08) == 0x08){
                    ((FakeButtonWrapper)DPadUp).IsRegisterDown = true;
                }else{
                    ((FakeButtonWrapper)DPadUp).IsRegisterDown = false;
                }
                if ((mask & 0x10) == 0x10){
                    ((FakeButtonWrapper)DPadDown).IsRegisterDown = true;
                }else{
                    ((FakeButtonWrapper)DPadDown).IsRegisterDown = false;
                }
                if ((mask & 0x20) == 0x20){
                    ((FakeButtonWrapper)DPadLeft).IsRegisterDown = true;
                }else{
                    ((FakeButtonWrapper)DPadLeft).IsRegisterDown = false;
                }
                if ((mask & 0x40) == 0x40){
                    ((FakeButtonWrapper)DPadRight).IsRegisterDown = true;
                }else{
                    ((FakeButtonWrapper)DPadRight).IsRegisterDown = false;
                }
            }

            ((FakeButtonWrapper)A).SetState((InputWrapper.ButtonState)pr.ReadByte());

            ((FakeButtonWrapper)B).SetState((InputWrapper.ButtonState)pr.ReadByte());

            ((FakeButtonWrapper)Back).SetState((InputWrapper.ButtonState)pr.ReadByte());

            float x = pr.ReadSingle();
            float y = pr.ReadSingle();

            LeftStick.Update(new Vector2(x, y));

            ((FakeButtonWrapper)DPadUp).SetState((InputWrapper.ButtonState)pr.ReadByte());

            ((FakeButtonWrapper)DPadDown).SetState((InputWrapper.ButtonState)pr.ReadByte());

            ((FakeButtonWrapper)DPadLeft).SetState((InputWrapper.ButtonState)pr.ReadByte());

            ((FakeButtonWrapper)DPadRight).SetState((InputWrapper.ButtonState)pr.ReadByte());
        }

        public override void Update()
        {
            ((FakeButtonWrapper)A).SetNone();

            ((FakeButtonWrapper)B).SetNone();

            ((FakeButtonWrapper)Back).SetNone();

            LeftStick.Update(Vector2.Zero);

            ((FakeButtonWrapper)DPadUp).SetNone();

            ((FakeButtonWrapper)DPadDown).SetNone();

            ((FakeButtonWrapper)DPadLeft).SetNone();
            ((FakeButtonWrapper)DPadRight).SetNone();
#if !ZUNE
            Start.Update();
            X.Update();
            Y.Update();
            LeftBumper.Update();
            RightBumper.Update();
            RightStick.Update(Vector2.Zero);
#endif
        }

        protected override void SetupButtons()
        {
            A = new FakeButtonWrapper(Buttons.A, _index);
            B = new FakeButtonWrapper(Buttons.B, _index);
            Back = new FakeButtonWrapper(Buttons.Back, _index);
            LeftStick = new ThumbStick();
            DPadDown = new FakeButtonWrapper(Buttons.DPadDown, _index);
            DPadUp = new FakeButtonWrapper(Buttons.DPadUp, _index);
            DPadLeft = new FakeButtonWrapper(Buttons.DPadLeft, _index);
            DPadRight = new FakeButtonWrapper(Buttons.DPadRight, _index);
#if !ZUNE
            Start = new FakeButtonWrapper(Buttons.Start, _index);
            X = new FakeButtonWrapper(Buttons.X, _index);
            Y = new FakeButtonWrapper(Buttons.Y, _index);
            LeftBumper = new FakeButtonWrapper(Buttons.LeftShoulder, _index);
            RightBumper = new FakeButtonWrapper(Buttons.RightShoulder, _index);
            RightStick = new ThumbStick();
#endif
        }
        public void SetState(Buttons b, Pauliver.ButtonWrapper.ButtonState state)
        {
            switch (b)
            {
                case Buttons.A:
                    ((FakeButtonWrapper)A).SetState(state);
                    break;
                case Buttons.B:
                    ((FakeButtonWrapper)B).SetState(state);
                    break;
                case Buttons.Back:
                    ((FakeButtonWrapper)Back).SetState(state);
                    break;
                case Buttons.DPadDown:
                    ((FakeButtonWrapper)DPadDown).SetState(state);
                    break;
                case Buttons.DPadUp:
                    ((FakeButtonWrapper)DPadUp).SetState(state);
                    break;
                case Buttons.DPadRight:
                    ((FakeButtonWrapper)DPadRight).SetState(state);
                    break;
                case Buttons.DPadLeft:
                    ((FakeButtonWrapper)DPadLeft).SetState(state);
                    break;
#if !ZUNE
                    //add other buttons
#endif

            }
        }
    
        public void SetLeftStickState(Vector2 Value)
        {
            LeftStick.X = Value.X;
            LeftStick.Y = Value.Y;
        }
#if !ZUNE
        public void SetRightStickState(Vector2 Value)
        {
            RightStick.X = Value.X;
            RightStick.Y = Value.Y;
        }
#endif
    }

    public class GamePad
    {
        public struct ThumbStick
        {
            public float X;
            public float Y;
            public void Update(Vector2 vector)
            {
                X = vector.X;
                Y = vector.Y;
            }
        }

        public void Write(PacketWriter pw)
        {
            {
                byte mask = 0x00;

                if (A.IsRegisterDown)
                {
                    mask |= 0x01;// 10 00 00 00
                }
                if (B.IsRegisterDown)
                {
                    mask |= 0x02;// 01 00 00 00
                }
                if (Back.IsRegisterDown)
                {
                    mask |= 0x04;// 00 10 00 00
                }
                if (DPadUp.IsRegisterDown)
                {
                    mask |= 0x08;// 00 01 00 00
                }
                if (DPadLeft.IsRegisterDown)
                {
                    mask |= 0x10;// 00 00 10 00
                }
                if (DPadDown.IsRegisterDown)
                {
                    mask |= 0x20;// 00 00 01 00
                }
                if (DPadRight.IsRegisterDown)
                {
                    mask |= 0x40;// 00 00 00 10
                }
                pw.Write(mask);
            }

            pw.Write(A.GetStateForStreaming());

            pw.Write(B.GetStateForStreaming());

            pw.Write(Back.GetStateForStreaming());

            pw.Write(LeftStick.X);
            pw.Write(LeftStick.Y);

            pw.Write(DPadUp.GetStateForStreaming());

            pw.Write(DPadDown.GetStateForStreaming());

            pw.Write(DPadLeft.GetStateForStreaming());

            pw.Write(DPadRight.GetStateForStreaming());
        }

        public ButtonWrapper A;
        public ButtonWrapper B;
        public ThumbStick LeftStick;
        public ButtonWrapper Back;
        public ButtonWrapper DPadUp;
        public ButtonWrapper DPadDown;
        public ButtonWrapper DPadLeft;
        public ButtonWrapper DPadRight;
#if !ZUNE
        public ButtonWrapper Start;
        public ButtonWrapper X;
        public ButtonWrapper Y;
        public ButtonWrapper LeftBumper;
        public ButtonWrapper RightBumper;
        public ThumbStick RightStick;
#endif

        protected PlayerIndex _index;
        public GamePad(PlayerIndex index)
        {
            _index = index;
            SetupButtons();
        }
        public GamePad(int Player)
        {
            _index = (PlayerIndex)(Player - 1);
            SetupButtons();
        }

        protected virtual void SetupButtons()
        {
            A = new ButtonWrapper(Buttons.A, _index);
            B = new ButtonWrapper(Buttons.B, _index);
            Back = new ButtonWrapper(Buttons.Back, _index);
            LeftStick = new ThumbStick();
            DPadDown = new ButtonWrapper(Buttons.DPadDown, _index);
            DPadUp = new ButtonWrapper(Buttons.DPadUp, _index);
            DPadRight = new ButtonWrapper(Buttons.DPadRight, _index);
            DPadLeft = new ButtonWrapper(Buttons.DPadLeft, _index);
#if !ZUNE
            Start = new ButtonWrapper(Buttons.Start, _index);
            X = new ButtonWrapper(Buttons.X, _index);
            Y = new ButtonWrapper(Buttons.Y, _index);
            LeftBumper = new ButtonWrapper(Buttons.LeftShoulder, _index);
            RightBumper = new ButtonWrapper(Buttons.RightShoulder, _index);
            RightStick = new ThumbStick();
#endif
        }

        public virtual void Update()
        {
            A.Update();
            B.Update();

            Back.Update();

            LeftStick.Update(Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)_index).ThumbSticks.Left);
            DPadUp.Update();
            DPadDown.Update();
            DPadLeft.Update();
            DPadRight.Update();

            //Zune 30 controls
            if (DPadDown.State == InputWrapper.ButtonState.Pressed || DPadDown.State == InputWrapper.ButtonState.Held)
            {
                LeftStick.Y -= 1;
            }
            if (DPadUp.State == InputWrapper.ButtonState.Pressed || DPadUp.State == InputWrapper.ButtonState.Held)
            {
                LeftStick.Y += 1;
            }
            if (DPadLeft.State == InputWrapper.ButtonState.Pressed || DPadLeft.State == InputWrapper.ButtonState.Held)
            {
                LeftStick.X -= 1;
            }
            if (DPadRight.State == InputWrapper.ButtonState.Pressed || DPadRight.State == InputWrapper.ButtonState.Held)
            {
                LeftStick.X += 1;
            }
#if !ZUNE
            Start.Update();
            X.Update();
            Y.Update();
            LeftBumper.Update();
            RightBumper.Update();
            RightStick.Update(Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)_index).ThumbSticks.Right);
#endif
        }
    }

#if WINDOWS
    public class KeyBoard
    {
        public KeyboardWrapper W;
        public KeyboardWrapper A;
        public KeyboardWrapper S;
        public KeyboardWrapper D;

        public KeyboardWrapper E;

        public KeyboardWrapper Q;
        public KeyboardWrapper U;
        
        public KeyboardWrapper Up;
        public KeyboardWrapper Down;
        public KeyboardWrapper Left;
        public KeyboardWrapper Right;

        public KeyboardWrapper Space;
        public KeyboardWrapper Enter;
        public KeyboardWrapper Plus;
        public KeyboardWrapper Minus;
        public KeyboardWrapper Escape;

        public KeyboardWrapper Tab;

        public KeyBoard()
        {
            W = new KeyboardWrapper(Keys.W);
            A = new KeyboardWrapper(Keys.A);
            S = new KeyboardWrapper(Keys.S);
            D = new KeyboardWrapper(Keys.D);

            E = new KeyboardWrapper(Keys.E);

            Q = new KeyboardWrapper(Keys.Q);
            U = new KeyboardWrapper(Keys.U);
            
            Plus = new KeyboardWrapper(Keys.Add);
            Minus = new KeyboardWrapper(Keys.Subtract);

            Up = new KeyboardWrapper(Keys.Up);
            Down = new KeyboardWrapper(Keys.Down);
            Left = new KeyboardWrapper(Keys.Left);
            Right = new KeyboardWrapper(Keys.Right);

            Space = new KeyboardWrapper(Keys.Space);
            Enter = new KeyboardWrapper(Keys.Enter);
            Escape = new KeyboardWrapper(Keys.Escape);

            Tab = new KeyboardWrapper(Keys.Tab);
        }

        public void Update()
        {
            W.Update();
            A.Update();
            S.Update();
            D.Update();

            E.Update();

            Q.Update();
            U.Update();

            Up.Update();
            Down.Update();
            Left.Update();
            Right.Update();

            Space.Update();
            Enter.Update();
            Plus.Update();
            Minus.Update();
            Escape.Update();

            Tab.Update();
        }
    }
#endif


    public abstract class InputWrapper
    {
        protected bool RegisterDown = true;
        protected ButtonState _State;
        public enum ButtonState :byte { Held, Pressed, None };

        public abstract void Update();
        public ButtonState State
        {
            get
            {
                return _State;
            }
        }

        public bool SinglePress
        {
            get
            {
                if (_State == ButtonState.Held && RegisterDown)
                {
                    RegisterDown = false;
                    _State = ButtonState.None;
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }

        public bool IsRegisterDown
        {
            get
            {
                return RegisterDown;
            }
            set
            {
                RegisterDown = value;
            }
        }
    }


    public class FakeButtonWrapper : ButtonWrapper
    {

        public FakeButtonWrapper(Microsoft.Xna.Framework.Input.Buttons button, PlayerIndex Player)
            : base(button, Player)
        {
        }
        protected override void SetStateFromInput()
        {
            //prevent base from being called
            //base.SetStateFromInput();
        }
        public override void Update()
        {
            _State = ButtonState.None;
        }

        public void ClearRegisterDown()
        {
            RegisterDown = true;
        }

        public void SetPress()
        {
            _State = ButtonState.Pressed;
        }
        public void SetHeld()
        {
            _State = ButtonState.Held;
        }
        public void SetNone()
        {
            _State = ButtonState.None;
        }
        public void SetState(ButtonState state)
        {
            _State = state; ;
        }
    }

    public class ButtonWrapper : InputWrapper
    {
        protected Microsoft.Xna.Framework.Input.Buttons T;
        protected PlayerIndex P;

        public ButtonWrapper(Microsoft.Xna.Framework.Input.Buttons button,PlayerIndex Player)
        {
            T = button;
            P = Player;
            _State = ButtonState.None;
            SetStateFromInput();
        }

        protected virtual void SetStateFromInput()
        {
            switch (T)
            {
                case Buttons.A:
                    if (Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)P).Buttons.A == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                    {
                        if (RegisterDown)
                            _State = ButtonState.Held;
                    }
                    else
                    {
                        if (RegisterDown)
                        {
                            if (_State == ButtonState.Held)
                            {
                                _State = ButtonState.Pressed;
                            }
                            else
                            {
                                _State = ButtonState.None;
                            }
                        }
                        else //RegisterDown == false
                        {
                            RegisterDown = true;
                        }
                    }
                    break;
                case Buttons.B:
                    if (Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)P).Buttons.B == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                    {
                        if (RegisterDown)
                            _State = ButtonState.Held;
                    }
                    else
                    {
                        if (RegisterDown)
                        {
                            if (_State == ButtonState.Held)
                            {
                                _State = ButtonState.Pressed;
                            }
                            else
                            {
                                _State = ButtonState.None;
                            }
                        }
                        else //RegisterDown == false
                        {
                            RegisterDown = true;
                        }
                    }
                    break;
                case Buttons.Back:
                    if (Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)P).Buttons.Back == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                    {
                        if (RegisterDown)
                            _State = ButtonState.Held;
                    }
                    else
                    {
                        if (RegisterDown)
                        {
                            if (_State == ButtonState.Held)
                            {
                                _State = ButtonState.Pressed;
                            }
                            else
                            {
                                _State = ButtonState.None;
                            }
                        }
                        else //RegisterDown == false
                        {
                            RegisterDown = true;
                        }
                    }
                    break;
                case Buttons.DPadDown:
                    if (Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)P).DPad.Down == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                    {
                        if (RegisterDown)
                            _State = ButtonState.Held;
                    }
                    else
                    {
                        if (RegisterDown)
                        {
                            if (_State == ButtonState.Held)
                            {
                                _State = ButtonState.Pressed;
                            }
                            else
                            {
                                _State = ButtonState.None;
                            }
                        }
                        else //RegisterDown == false
                        {
                            RegisterDown = true;
                        }
                    }
                    break;
                case Buttons.DPadLeft:
                    if (Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)P).DPad.Left == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                    {
                        if (RegisterDown)
                            _State = ButtonState.Held;
                    }
                    else
                    {
                        if (RegisterDown)
                        {
                            if (_State == ButtonState.Held)
                            {
                                _State = ButtonState.Pressed;
                            }
                            else
                            {
                                _State = ButtonState.None;
                            }
                        }
                        else //RegisterDown == false
                        {
                            RegisterDown = true;
                        }
                    }
                    break;
                case Buttons.DPadRight:
                    if (Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)P).DPad.Right == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                    {
                        if (RegisterDown)
                            _State = ButtonState.Held;
                    }
                    else
                    {
                        if (RegisterDown)
                        {
                            if (_State == ButtonState.Held)
                            {
                                _State = ButtonState.Pressed;
                            }
                            else
                            {
                                _State = ButtonState.None;
                            }
                        }
                        else //RegisterDown == false
                        {
                            RegisterDown = true;
                        }
                    }
                    break;
                case Buttons.DPadUp:
                    if (Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)P).DPad.Up == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                    {
                        if (RegisterDown)
                            _State = ButtonState.Held;
                    }
                    else
                    {
                        if (RegisterDown)
                        {
                            if (_State == ButtonState.Held)
                            {
                                _State = ButtonState.Pressed;
                            }
                            else
                            {
                                _State = ButtonState.None;
                            }
                        }
                        else //RegisterDown == false
                        {
                            RegisterDown = true;
                        }
                    }
                    break;
#if !ZUNE
                case Buttons.LeftShoulder:
                    if (Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)P).Buttons.LeftShoulder == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                    {
                        if (RegisterDown)
                            _State = ButtonState.Held;
                    }
                    else
                    {
                        if (RegisterDown)
                        {
                            if (_State == ButtonState.Held)
                            {
                                _State = ButtonState.Pressed;
                            }
                            else
                            {
                                _State = ButtonState.None;
                            }
                        }
                        else //RegisterDown == false
                        {
                            RegisterDown = true;
                        }
                    }
                    break;
                case Buttons.LeftStick:
                    if (Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)P).Buttons.LeftStick == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                    {
                        if (RegisterDown)
                            _State = ButtonState.Held;
                    }
                    else
                    {
                        if (RegisterDown)
                        {
                            if (_State == ButtonState.Held)
                            {
                                _State = ButtonState.Pressed;
                            }
                            else
                            {
                                _State = ButtonState.None;
                            }
                        }
                        else //RegisterDown == false
                        {
                            RegisterDown = true;
                        }
                    }
                    break;
                case Buttons.LeftTrigger:
                    if (Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)P).Triggers.Right == 1.0f)
                    {
                        if (RegisterDown)
                            _State = ButtonState.Held;
                    }
                    else
                    {
                        if (RegisterDown)
                        {
                            if (_State == ButtonState.Held)
                            {
                                _State = ButtonState.Pressed;
                            }
                            else
                            {
                                _State = ButtonState.None;
                            }
                        }
                        else //RegisterDown == false
                        {
                            RegisterDown = true;
                        }
                    }
                    break;
                case Buttons.RightShoulder:
                    if (Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)P).Buttons.RightShoulder == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                    {
                        if (RegisterDown)
                            _State = ButtonState.Held;
                    }
                    else
                    {
                        if (RegisterDown)
                        {
                            if (_State == ButtonState.Held)
                            {
                                _State = ButtonState.Pressed;
                            }
                            else
                            {
                                _State = ButtonState.None;
                            }
                        }
                        else //RegisterDown == false
                        {
                            RegisterDown = true;
                        }
                    }
                    break;
                case Buttons.RightStick:
                    if (Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)P).Buttons.RightStick == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                    {
                        if (RegisterDown)
                           _State = ButtonState.Held;
                    }
                    else
                    {
                        if (RegisterDown)
                        {
                            if (_State == ButtonState.Held)
                            {
                                _State = ButtonState.Pressed;
                            }
                            else
                            {
                                _State = ButtonState.None;
                            }
                        }
                        else //RegisterDown == false
                        {
                            RegisterDown = true;
                        }
                    }
                    break;
                case Buttons.RightTrigger:
                    if (Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)P).Triggers.Right == 1.0f)
                    {
                        if (RegisterDown)
                            _State = ButtonState.Held;
                    }
                    else
                    {
                        if (RegisterDown)
                        {
                            if (_State == ButtonState.Held)
                            {
                                _State = ButtonState.Pressed;
                            }
                            else
                            {
                                _State = ButtonState.None;
                            }
                        }
                        else //RegisterDown == false
                        {
                            RegisterDown = true;
                        }
                    }
                    break;
                case Buttons.Start:
                    if (Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)P).Buttons.Start == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                    {
                        if (RegisterDown)
                            _State = ButtonState.Held;
                    }
                    else
                    {
                        if (RegisterDown)
                        {
                            if (_State == ButtonState.Held)
                            {
                                _State = ButtonState.Pressed;
                            }
                            else
                            {
                                _State = ButtonState.None;
                            }
                        }
                        else //RegisterDown == false
                        {
                            RegisterDown = true;
                        }
                    }
                    break;
                case Buttons.X:
                    if (Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)P).Buttons.X == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                    {
                        if (RegisterDown)
                            _State = ButtonState.Held;
                    }
                    else
                    {
                        if (RegisterDown)
                        {
                            if (_State == ButtonState.Held)
                            {
                                _State = ButtonState.Pressed;
                            }
                            else
                            {
                                _State = ButtonState.None;
                            }
                        }
                        else //RegisterDown == false
                        {
                            RegisterDown = true;
                        }
                    }
                    break;
                case Buttons.Y:
                    if (Microsoft.Xna.Framework.Input.GamePad.GetState((Microsoft.Xna.Framework.PlayerIndex)P).Buttons.Y == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
                    {
                        if (RegisterDown)
                            _State = ButtonState.Held;
                    }
                    else
                    {
                        if (RegisterDown)
                        {
                            if (_State == ButtonState.Held)
                            {
                                _State = ButtonState.Pressed;
                            }
                            else
                            {
                                _State = ButtonState.None;
                            }
                        }
                        else //RegisterDown == false
                        {
                            RegisterDown = true;
                        }
                    }
                    break;
#endif
            }
        }

        public override void Update()
        {
            SetStateFromInput();
        }

        public byte GetStateForStreaming()
        {
            return (byte)_State;
        }
    }
#if WINDOWS
    public class KeyboardWrapper : InputWrapper
    {
        protected Microsoft.Xna.Framework.Input.Keys T;

        public KeyboardWrapper(Microsoft.Xna.Framework.Input.Keys Key)
        {
            T = Key;
            _State = ButtonState.None;
            SetStateFromInput();
        }

        protected void SetStateFromInput()
        {
            if (Microsoft.Xna.Framework.Input.Keyboard.GetState().IsKeyDown(T))
            {
                if(RegisterDown)
                    _State = ButtonState.Held;
            }
            if (Microsoft.Xna.Framework.Input.Keyboard.GetState().IsKeyUp(T))
            {
                if (RegisterDown)
                {
                    if (_State == ButtonState.Held)
                    {
                        _State = ButtonState.Pressed;
                    }
                    else
                    {
                        _State = ButtonState.None;
                    }
                }
                else //RegisterDown == false
                {
                    RegisterDown = true;
                }
            }
        }

        public override void Update()
        {
            SetStateFromInput();
        }

    }
#endif
    #endregion

    public class PInput
    {
        protected static PInput _Instance;
        public static PInput Instance
        {
            get
            {
                if (_Instance == null)
                {
                    _Instance = new PInput();
                }
                return _Instance;
            }
        }
#if WINDOWS
        protected KeyBoard _Keyboard;
#endif
        protected GamePad _GamePad1;
        public GamePad GamePad1
        {
            get
            {
                return _GamePad1;
            }
        }
        protected GamePad _GamePad2;
        public GamePad GamePad2
        {
            get
            {
                return _GamePad2;
            }
        }
        protected GamePad _GamePad3;
        public GamePad GamePad3
        {
            get
            {
                return _GamePad3;
            }
        }
        protected GamePad _GamePad4;
        public GamePad GamePad4
        {
            get
            {
                return _GamePad4;
            }
        }
        //@@ this should be handled in a different way
        public bool Is1Human = true;
        public bool Is2Human = false;
        public bool Is3Human = false;
        public bool Is4Human = false;

        protected PInput()
        {
#if WINDOWS
            _Keyboard = new KeyBoard();
#endif
            _GamePad1 = new GamePad(PlayerIndex.One);
            _GamePad2 = null;
            _GamePad3 = null;
            _GamePad4 = null;
#if !ZUNE
            _GamePad2 = new GamePad(PlayerIndex.Two);
            _GamePad3 = new GamePad(PlayerIndex.Three);
            _GamePad4 = new GamePad(PlayerIndex.Four);
#endif
        }

        public void SetFakeGamePad(int i,PlayerIndex index)
        {
            switch(i)
            {
                //case 1:
                    //_GamePad1 = new FakeGamePad(index);
                    //break;
                case 2:
                    _GamePad2 = new FakeGamePad(index);
                    break;
                case 3:
                    _GamePad3 = new FakeGamePad(index);
                    break;
                case 4:
                    _GamePad4 = new FakeGamePad(index);
                    break;
            }
        }

        public void ResetGamePads()
        {
#if !ZUNE
            _GamePad2 = new GamePad(PlayerIndex.Two);
            _GamePad3 = new GamePad(PlayerIndex.Three);
            _GamePad4 = new GamePad(PlayerIndex.Four);
#else
            _GamePad2 = null;
            _GamePad3 = null;
            _GamePad4 = null;
#endif
        }

        public void Update()
        {
#if WINDOWS
            _Keyboard.Update();
#endif
            _GamePad1.Update();
            if(_GamePad2 != null)
                _GamePad2.Update();
            if (_GamePad3 != null)
                _GamePad3.Update();
            if (_GamePad4 != null)
                _GamePad4.Update();

        }
#if WINDOWS
        public KeyBoard Keyboard
        {
            get
            {
                return _Keyboard;
            }
        }
#endif

        public void ReadInputFromNetwork(PlayerIndex index, PacketReader pr)
        {
            if ( !(GamePad(index) is FakeGamePad) )
            {
                pr.ReadInt32();
                pr.ReadBoolean();

                pr.ReadInt32();
                pr.ReadBoolean();

                pr.ReadInt32();
                pr.ReadBoolean();

                float x = (float)pr.ReadDouble();
                float y = (float)pr.ReadDouble();

                pr.ReadInt32();
                pr.ReadBoolean();

                pr.ReadInt32();
                pr.ReadBoolean();
                return;
            }
            FakeGamePad fgp = (FakeGamePad)GamePad(index);
            fgp.Read(pr);
        }

        public void WriteInputToNetwork(PlayerIndex index, PacketWriter pr)
        {
            GamePad gp = GamePad(index);
            gp.Write(pr);
        }

        public GamePad GamePad(int index)
        {
            switch (index)
            {
                case 1:
                    return _GamePad1;
                case 2:
                    return _GamePad2;
                case 3:
                    return _GamePad3;
                case 4:
                    return _GamePad4;
            }
            return _GamePad1;
        }

        public GamePad GamePad(PlayerIndex index)
        {
            switch (index)
            {
                case PlayerIndex.One:
                    return _GamePad1;
                case PlayerIndex.Two:
                    return _GamePad2;
                case PlayerIndex.Three:
                    return _GamePad3;
                case PlayerIndex.Four:
                    return _GamePad4;
            }
            return _GamePad1;
        }

        public bool IsHuman(PlayerIndex index)
        {
            switch (index)
            {
                case PlayerIndex.One:
                    return Is1Human;
                case PlayerIndex.Two:
                    return Is2Human;
                case PlayerIndex.Three:
                    return Is3Human;
                case PlayerIndex.Four:
                    return Is4Human;
            }
            return false;
        }
    }

}
